<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="embroot.css">
<TITLE>
Communicating between Java and ECLiPSe using queues
</TITLE>
</HEAD>
<BODY >
<A HREF="embroot045.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot041.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="embroot047.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc89">8.5</A>&nbsp;&nbsp;Communicating between Java and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> using queues<A NAME="@default212"></A></H2><UL>
<LI><A HREF="embroot046.html#toc46">Opening, using and closing queues</A>
<LI><A HREF="embroot046.html#toc47">Opening a queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</A>
<LI><A HREF="embroot046.html#toc48">Writing and reading ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> terms on queues</A>
<LI><A HREF="embroot046.html#toc49">Using the <I>QueueListener</I> interface</A>
<LI><A HREF="embroot046.html#toc50">Access to ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>'s standard streams</A>
</UL>
 
<A NAME="sec:ji-using-queue-streams"></A>
In the Java-ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> Interface, <I>queues</I> are one-way data
streams used for communication between ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> and Java. These are
represented on the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side using &#8220;peer queues&#8221;, which are 
I/O streams. The Java-ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> Interface includes the classes <I>FromEclipseQueue</I> and <I>ToEclipseQueue</I> which represent these
queues on the Java side. <I>FromEclipseQueue</I> represents a queue
which can be written to in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> and read from in Java. A <I>ToEclipseQueue</I> is a queue which can be written to in Java and read
from in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>.<BR>
<BR>
Section <A HREF="#sec:ji-open-close">8.5.1</A> discusses how queues are opened,
<A NAME="@default213"></A>referenced and closed<A NAME="@default214"></A> from either the Java 
or ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> sides. We also discuss here how to transfer byte data in both
directions. However, the programmer need not be concerned with low-level
data operations on queues: whole terms can be written and read using the
<I>EXDRInputStream</I> and <I>EXDROutputStream</I> classes discussed in
Section
<A HREF="#sec:ji-formatting-queue-data">8.5.2</A>.<BR>
<BR>
Via the <I>QueueListener</I> feature<A NAME="@default215"></A>, Java
code can be invoked (in a sense) from within ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>. The use of this
feature is discussed in Section <A HREF="#sec:ji-queue-listeners">8.5.3</A>. In some
cases, the standard streams (<TT>stdin</TT>, <TT>stdout</TT> and <TT>stderr</TT>) of
the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> engine will be visible to Java as queues. How to use these
is discussed in Section <A HREF="#sec:ji-standard-streams">8.5.4</A>.<BR>
<BR>
<A NAME="toc46"></A>
<H3 CLASS="subsection"><A NAME="htoc90">8.5.1</A>&nbsp;&nbsp;Opening, using and closing queues<A NAME="@default216"></A></H3>
<A NAME="sec:ji-open-close"></A>
<A NAME="@default217"></A>
<A NAME="@default218"></A>
We now explain the standard sequence of events for using
queues. Opening and closing, can be performed in a single step from
either the Java or the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side.<BR>
<BR>

<H4 CLASS="subsubsection">Opening a queue using Java methods</H4>
<I>FromEclipseQueue</I> and <I>ToEclipseQueue</I> do not have public
constructors. Instead, we invoke <TT>getFromEclipseQueue</TT> or <TT>getToEclipseQueue</TT>. This asks the <I>EclipseConnection</I> object for a
reference to a <I>FromEclipseQueue</I> or <I>ToEclipseQueue</I> instance
which represents a new queue. To specify the stream for later
reference, we supply the method with a string which will equal to the
atom by which the queue is referred to as a stream in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>. For
example the following code creates two queues<A NAME="@default219"></A>, one in each direction:
<PRE CLASS="verbatim">
...
  ToEclipseQueue java_to_eclipse = 
    eclipse.getToEclipseQueue("java_to_eclipse");
  FromEclipseQueue eclipse_to_java = 
    eclipse.getFromEclipseQueue("eclipse_to_java");
...
</PRE>These methods will create and return new <I>FromEclipseQueue</I> or
<I>ToEclipseQueue</I> objects, and will also open streams with the
specified names on the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side. No stream in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> should
exist with the specified name. If a stream exists which has this name
and is not a queue between the Java object and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>, the Java
method throws an exception. If the name is used by a pre-existing
queue, it is returned, so the <TT>getFromEclipseQueue</TT> and <TT>getToEclipseQueue</TT> methods can also be used to retrieve the queue
objects by name once if they have already been created.<BR>
<BR>
<A NAME="toc47"></A>
<H3 CLASS="subsection">Opening a queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H3>
<A NAME="@default220"></A>
You can use the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> builtin <A HREF="../bips/kernel/externals/peer_queue_create-5.html"><B>peer_queue_create/5</B></A><A NAME="@default221"></A> to open a
queue. Used correctly, these have the same effect as the Java methods
explained above. For the peer name, you should use the atom returned
by the <TT>getPeerName()</TT> method of the relevant <I>EclipseConnection</I> instance. The direction should be <TT>fromec</TT> for
a <I>FromEclipseQueue</I> and <TT>toec</TT> for a <I>ToEclipseQueue</I>. The queue type should always be <TT>sync</TT>
(for asynchronous queues, refer to section <A >??</A>).<BR>
<BR>

<H4 CLASS="subsubsection">Transferring data using Java methods</H4>
On the Java side, once a <I>FromEclipseQueue</I> has been established,
you can treat it as you would any instance of <I>java.io.InputStream</I>, of which <I>FromEclipseQueue</I> is a
subclass. Similarly, <I>ToEclipseQueue</I> is a subclass of <I>java.io.OutputStream</I>. The only visible difference is that <I>FromEclipseQueue</I> and <I>ToEclipseQueue</I> instances may have <I>QueueListeners</I> attached, as is discussed in Section
<A HREF="#sec:ji-queue-listeners">8.5.3</A><A NAME="@default222"></A>. <BR>
<BR>

<H4 CLASS="subsubsection">Transferring data using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H4>
On the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side, there are built-in predicates for writing to,
reading from and otherwise interacting with streams. Any of these may
be used. Perhaps most useful are <A HREF="../bips/kernel/ioterm/read_exdr-2.html"><B>read_exdr/2</B></A><A NAME="@default223"></A> and <A HREF="../bips/kernel/ioterm/write_exdr-2.html"><B>write_exdr/2</B></A><A NAME="@default224"></A>; these are explained in Section
<A HREF="#sec:ji-formatting-queue-data">8.5.2</A><A NAME="@default225"></A>. For the stream ID, you may either use the stream name, or the stream number, obtained for example using <A HREF="../bips/kernel/externals/peer_get_property-3.html"><B>peer_get_property/3</B></A><A NAME="@default226"></A>.<BR>
<BR>

<H4 CLASS="subsubsection">Note: <B>always</B> flush</H4>
When communicating between Java and ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> using queues<A NAME="@default227"></A>, you
should always invoke the <TT>flush()</TT> method of the Java <I>OutputStream</I> which you have written to, whether it be a <I>ToEclipseQueue</I> or an <I>EXDROutputStream</I>. Similarly, on the
ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side, <TT>flush/1</TT> should always be executed after
writing. Although in some cases reading of the data is possible
without a flush, flushing guarantees the transfer of data.
<BR>
<BR>

<H4 CLASS="subsubsection">Closing a queue using Java methods</H4>
This is done simply by calling the <TT>close()</TT><A NAME="@default228"></A> method on the <I>FromEclipseQueue</I> or <I>ToEclipseQueue</I> instance.<BR>
<BR>

<H4 CLASS="subsubsection">Closing a queue using ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> predicates</H4>
<A NAME="@default229"></A>
This is done by executing the builtin <A HREF="../bips/kernel/externals/peer_queue_close-1.html"><B>peer_queue_close/1</B></A><A NAME="@default230"></A>. Note
that the builtin <TT>close/1</TT> should not be used in this situation,
as it will not terminate the Java end of the queue.<BR>
<BR>
<A NAME="toc48"></A>
<H3 CLASS="subsection"><A NAME="htoc91">8.5.2</A>&nbsp;&nbsp;Writing and reading ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> terms on queues<A NAME="@default231"></A></H3>
<A NAME="sec:ji-formatting-queue-data"></A>
Rather than dealing with low-level data I/O instructions such as reading
and writing bytes, the Java-ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> Interface provides classes for
reading and writing whole terms. In the underlying implementation of these
classes, the EXDR (ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> eXternal Data Representation) format is
used<A NAME="@default232"></A>. This allows ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> to communicate with other
languages using a common data type. However, it is not necessary for the
API user to know about EXDR in detail to use the Java-ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> Interface
features discussed in this section.<BR>
<BR>
<I>EXDRInputStream</I> is a subclass of <I>java.io.DataInputStream</I> which can read EXDR format. <I>EXDROutputStream</I> is a subclass of <I>java.io.FilterOutputStream</I> which can write EXDR format.<BR>
<BR>

<H4 CLASS="subsubsection">Initialising <I>EXDRInputStream</I> and <I>EXDROutputStream</I></H4>
<A NAME="@default233"></A>
The constructor for <I>EXDRInputStream</I> takes an instance of <I>java.io.InputStream</I> as a parameter. This parameter stream is the
source of the EXDR data for the new stream. If data has been written
to the <I>InputStream</I> in EXDR format, you can access it by invoking
the <TT>readTerm</TT> method of the new <I>EXDRInputStream</I>. This
will read the data from the <I>InputStream</I> and translate the EXDR
format into the Java representation of the data, which is then
returned by <TT>readTerm</TT>.<BR>
<BR>
Similarly, the constructor for <I>EXDROutputStream</I> takes an
instance of <I>java.io.OutputStream</I> as a parameter. This parameter
stream is the destination of the data written to the new stream. You
write data by invoking the <TT>write</TT> method of the stream. The
parameter of this method is a Java object representing the piece of
data to be written. The class of this object can be any of the Java
classes mentioned in Table <A HREF="embroot044.html#tab:ec-java-data">8.1</A>. The object gets
translated into EXDR format and this is written to the destination
<I>OutputStream</I>.<BR>
<BR>

<H4 CLASS="subsubsection"><I>EXDRInputStream</I> and <I>EXDROutputStream</I> at work</H4>
<A NAME="@default234"></A>
Although the underlying stream could be any kind of stream (e.g. a
file stream), the most common use of <I>EXDRInputStream</I> and <I>EXDROutputStream</I> is to read data from and write data to queues<A NAME="@default235"></A> in
EXDR format. In other words, we usually wrap these classes around <I>FromEclipseQueue</I> and <I>ToEclipseQueue</I> classes. We now look at an
example which does just this.<BR>
<BR>
The example is in these two files: 
<BLOCKQUOTE CLASS="quote">
<A HREF="../examples/JavaInterface/QueueExample1.java"><TT>&lt;eclipse_dir&gt;</TT><TT>/doc/examples/JavaInterface</TT><TT>/QueueExample1.java</TT></A><BR>
<A HREF="../examples/JavaInterface/queue_example_1.pl"><TT>&lt;eclipse_dir&gt;</TT><TT>/doc/examples/JavaInterface</TT><TT>/queue_example_1.pl</TT></A>
</BLOCKQUOTE>
The Java program's first relevant action is to invoke the <TT>compile</TT> method of the <I>EclipseEngine</I>. This causes the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>
program to be loaded by ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> engine. After <TT>compile</TT>
completes, the Java program creates a <I>ToEclipseQueue</I> and a <I>FromEclipseQueue</I>, with the following lines:
<PRE CLASS="verbatim">
    // Create the two queues
    java_to_eclipse = eclipse.getToEclipseQueue("java_to_eclipse");
    eclipse_to_java = eclipse.getFromEclipseQueue("eclipse_to_java");
</PRE>Then in the next two lines we create an <I>EXDROutputStream</I> to
format data going to <TT>java_to_eclipse</TT> and an <I>EXDRInputStream</I> to format data coming from <TT>eclipse_to_java</TT>.
<PRE CLASS="verbatim">
    // Set up the two formatting streams
    java_to_eclipse_formatted = new EXDROutputStream(java_to_eclipse);
    eclipse_to_java_formatted = new EXDRInputStream(eclipse_to_java);
</PRE>The Java program writes two atoms to <TT>java_to_eclipse_formatted</TT>, and then flushes the stream. This
causes each atom to be translated into EXDR format and the translation
to then be written on to <TT>java_to_eclipse</TT>. The Java program then
makes an <TT>rpc</TT><A NAME="@default236"></A> invocation to the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> program's only predicate
<TT>read_2_write_1/0</TT>, which is defined as follows:
<PRE CLASS="verbatim">
read_2_write_1:-
        read_exdr(java_to_eclipse, Term1),
        read_exdr(java_to_eclipse, Term2),
        write_exdr(eclipse_to_java, pair(Term1, Term2)),
        flush(eclipse_to_java).
</PRE>The built-in <A HREF="../bips/kernel/ioterm/read_exdr-2.html"><B>read_exdr/2</B></A><A NAME="@default237"></A> reads a term's worth of data from the
stream supplied and instantiates it to the second argument. So <TT>read_2_write_1/0</TT> reads the two terms from the stream. They are
then written on to the <TT>eclipse_to_java</TT> stream within a <TT>pair(...)</TT> functor using the built-in <A HREF="../bips/kernel/ioterm/write_exdr-2.html"><B>write_exdr/2</B></A><A NAME="@default238"></A>, and the
stream is flushed. When the predicate succeeds, the <TT>rpc</TT><A NAME="@default239"></A> invocation
returns and the term data is on <TT>eclipse_to_java</TT> in EXDR
format. The next step of the java program is the following:
<PRE CLASS="verbatim">
    System.out.println(eclipse_to_java_formatted.readTerm());
</PRE>Since <TT>eclipse_to_java</TT> was the <I>FromEclipseQueue</I> passed as a
parameter when <TT>eclipse_to_java_formatted</TT> was initialised, the
<TT>readTerm</TT> method of this object reads the EXDR data which is on
<TT>eclipse_to_java</TT> and converts it into the appropriate Object to
represent the piece of data, in this case a <TT>CompoundTerm</TT>. This Object is
then returned by <TT>readTerm</TT>. Hence the output of the program is
<TT>pair(a,b)</TT>.<BR>
<BR>
<A NAME="toc49"></A>
<H3 CLASS="subsection"><A NAME="htoc92">8.5.3</A>&nbsp;&nbsp;Using the <I>QueueListener</I> interface</H3>
<A NAME="sec:ji-queue-listeners"></A>
<A NAME="@default240"></A>
It may sometimes be useful to have Java react automatically to data
arriving on a queue from ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>. An example of this would
be where a Java program has a graphical display monitoring the state
of search in ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>. We would like ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> to be able to send a
message along a queue every time an element of the search state
updates, and have Java react with some appropriate graphical action
according to the message.<BR>
<BR>
Similarly, ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> may require information from a Java database at
some point during its operation. Again we could use a queue to
transfer this information. If ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> tries to read from this queue
when it is empty, we would like Java to step in and supply the next
piece of data. <BR>
<BR>
The <I>QueueListener</I> interface is the means by which handlers are
attached to queues<A NAME="@default241"></A> on the Java side so that Java reacts
automatically to ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>'s interaction with the queue.<BR>
<BR>
Any object which implements the <I>QueueListener</I> interface can be
attached to either a <I>FromEclipseQueue</I> or a <I>ToEclipseQueue</I>, using
the <TT>setListener</TT> method. The <I>QueueListener</I> can be removed
using <TT>removeListener</TT>. Queues<A NAME="@default242"></A> can only have one Java
listener at any one time. <BR>
<BR>
The <I>QueueListener</I> interface has two methods: <TT>dataAvailable</TT>
and <TT>dataRequest</TT>. 
<DL CLASS="description" COMPACT=compact><DT CLASS="dt-description">
<B><TT>dataAvailable</TT></B><DD CLASS="dd-description"> is invoked only if the <I>QueueListener</I> is 
 attached to a <I>FromEclipseQueue</I>. It is invoked when the queue is 
 flushed on the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> side.
<DT CLASS="dt-description"><B><TT>dataRequest</TT></B><DD CLASS="dd-description"> is invoked only if the <I>QueueListener</I> is 
 attached to a <I>ToEclipseQueue</I>. It is invoked when ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> tries
 to read from the queue when it is empty<SUP><A NAME="text8" HREF="embroot041.html#note8">1</A></SUP>.
</DL>
Both methods have a single <I>Object</I> parameter named <TT>source</TT>. When they are invoked this parameter is the <I>FromEclipseQueue</I>
or <I>ToEclipseQueue</I> on which the flush or read happened.<BR>
<BR>
There is an example Java program <TT>QueueExample2.java</TT> with an
accompanying example ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> program <TT>queue_example_2.pl</TT>
which use <I>QueueListeners</I> attached to queues going in both
directions.
<BLOCKQUOTE CLASS="quote">
<A HREF="../examples/JavaInterface/QueueExample2.java"><TT>&lt;eclipse_dir&gt;</TT><TT>/doc/examples/JavaInterface</TT><TT>/QueueExample2.java</TT></A><BR>
<A HREF="../examples/JavaInterface/queue_example_2.pl"><TT>&lt;eclipse_dir&gt;</TT><TT>/doc/examples/JavaInterface</TT><TT>/queue_example_2.pl</TT></A>
</BLOCKQUOTE>
After the queues streams are set up on both sides, the Java program
attaches as listeners a <I>TermProducer</I> to the <I>ToEclipseQueue</I>
and a <I>TermConsumer</I> to the <I>FromEclipseQueue</I>. These are both
locally defined classes which implement <I>QueueListener</I>. The <I>TermProducer</I>, each time its <TT>dataRequest</TT> method is invoked, sends
one of five different atoms down its queue in EXDR format<A NAME="@default243"></A>. The
<I>TermConsumer</I>, when its <TT>dataAvailable</TT> method is invoked,
reads some EXDR data from its queue and translates it into the
appropriate Java object. It then writes this object out to stdout.<BR>
<BR>
Next, the Java program, using <TT>rpc</TT><A NAME="@default244"></A>, executes the only predicate
in the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> program: <TT>read_5_write_5/0</TT>. This repeats the
following operation five times: read in a term in EXDR format from the
relevant incoming stream, write it out in EXDR format with an
extra functor to the relevant outgoing stream, and flush the
outgoing stream.<BR>
<BR>
<A NAME="toc50"></A>
<H3 CLASS="subsection"><A NAME="htoc93">8.5.4</A>&nbsp;&nbsp;Access to ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>'s standard streams</H3>
<A NAME="sec:ji-standard-streams"></A>
If the object representing the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> implements the <I>EclipseEngine</I> <A NAME="@default245"></A> interface, then the API user
may have access to the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>'s standard streams (see Section
<A HREF="embroot048.html#sec:ji-use-queues-flag">8.7.2</A>). These are returned as <I>FromEclipseQueue</I>s and <I>ToEclipseQueue</I>s by the methods <TT>getEclipseStdin</TT>, <TT>getEclipseStdout</TT> and <TT>getEclipseStderr</TT>.<BR>
<BR>
<HR>
<A HREF="embroot045.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="embroot041.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="embroot047.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
